package com.example.demo.service.Portrait.impl;

import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.domain.entity.ExamPortrait;
import com.example.demo.domain.exam.ExamUserScore;
import com.example.demo.dto.PortraitDto.*;
import com.example.demo.mapper.ExamUserScoreMapper;
import com.example.demo.mapper.ProblemMapper;
import com.example.demo.service.ExamPortraitService;
import com.example.demo.service.Portrait.PortraitService;
import com.example.demo.service.VojSubmissionsService;
import com.example.demo.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.Max;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PortraitServiceImpl implements PortraitService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PortraitServiceImpl.class);

    @Resource
    private ProblemMapper problemMapper;

    @Resource
    private  ExamUserScoreMapper examUserScoreMapper;

    @Resource
    private ExamPortraitService examPortraitService;

    @Resource
    private VojSubmissionsService vojSubmissionsService;

    @Transactional
    @Override
    public void examUserPortrait(List<ExamPortraitDto> examPortraitDtos) {
        if (CollectionUtils.isEmpty(examPortraitDtos)){
            return;
        }
        LOGGER.info(examPortraitDtos.get(0).getExamId()+":用户画像生成开始");

        // 获取题目id和题目名字的map
        HashMap<Long, String> questionIdOfName = new HashMap<>();
        if (!CollectionUtils.isEmpty(examPortraitDtos.get(0).getCodeCapacities())){
            for (CodeCapacity codeCapacity : examPortraitDtos.get(0).getCodeCapacities()) {
                questionIdOfName.put(codeCapacity.getQuestionId(),codeCapacity.getQuestionName());
            }
        }

        // 用于总分排序 所有考试总分
        List<BigDecimal> sumScoreList = new ArrayList<>();

        // 用于技能突破数据  tagMapList《知识点标签，所有考试实际得分》
        Map<String,List<BigDecimal>> tagMapList = new HashMap<String,List<BigDecimal>>();

        // 获取本次考试编程题目信息
//        List<Long> questionIds =new ArrayList<>();
        // 每个题目最高分
//        Map<Long,BigDecimal> maxScore = new HashMap<>();
//        for (RepetitionRateDto repetitionRateDto : examPortraitDtos.get(0).getAbnormalRiskWarningDto().getRepetitionRateDtoList()) {
//            questionIds.add(repetitionRateDto.getQuestionId());
//            maxScore.put(repetitionRateDto.getQuestionId(),new BigDecimal(0));
//        }

        // 用于组装排序等需要的数据
        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
            if (!sumScoreList.contains(examPortraitDto.getComprehensiveEvaluationDto().getScore())){
                sumScoreList.add(examPortraitDto.getComprehensiveEvaluationDto().getScore());
            }

            // 用于技能突破数据
            if (!CollectionUtils.isEmpty(examPortraitDto.getSkillMapDtoList())){
                // 获取 并遍历 技能数SkillMap实体类 -> 更新tagmap 提炼出需要的信息（标签）
                for (SkillMapDto skillMapDto : examPortraitDto.getSkillMapDtoList()) {
                    if (CollectionUtils.isEmpty(tagMapList.get(skillMapDto.getTagName()))){
                        List<BigDecimal> tempList = new ArrayList<>();
                        tagMapList.put(skillMapDto.getTagName(),tempList);
                    }
                    if (!tagMapList.get(skillMapDto.getTagName()).contains(skillMapDto.getActualSumScore())){
                        tagMapList.get(skillMapDto.getTagName()).add(skillMapDto.getActualSumScore());
                    }
                }
            }
        }

        // 填充codeCapacities的非元数据属性，编程能力
        double maxEfficientTime = fillCodeCapacities(examPortraitDtos);
//        System.out.println("max: "+ maxEfficientTime);
        // 每道题的运行情况
        fiLlCodeSummarizeDtos(examPortraitDtos);
        //

        // 用于技能突破数据
        for (String s : tagMapList.keySet()) {
            //Collections.sort(tagMapList.get(s));
            Collections.sort(tagMapList.get(s), new Comparator<BigDecimal>() {
                @Override
                public int compare(BigDecimal o1, BigDecimal o2) {
                    return o2.compareTo(o1);
                }
            });
        }
        // 总分排序，降序
        Collections.sort(sumScoreList, new Comparator<BigDecimal>() {
            @Override
            public int compare(BigDecimal o1, BigDecimal o2) {
                return o2.compareTo(o1);
            }
        });


        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
            LOGGER.info("考生："+examPortraitDto.getUsername()+":用户画像生成开始");
            examPortraitDto.setMaxEfficientTime(maxEfficientTime);
            // 处理综合评价，生成排名
            comprehensiveEvaluationDtoHandler(examPortraitDto.getComprehensiveEvaluationDto(),sumScoreList);
            // 处理技能图谱,生成 score（ActualSumScore / SumScore）、排名
            skillMapDtoHandler(tagMapList,examPortraitDto.getSkillMapDtoList());
            // 历史数据处理
            durationScoreRecordDtoHandler(examPortraitDto);

            // 补充题目名称
            if (null != examPortraitDto.getAbnormalRiskWarningDto() && !CollectionUtils.isEmpty(examPortraitDto.getAbnormalRiskWarningDto().getQuesTionIntervalDtos())){
                for (QuesTionIntervalDto quesTionIntervalDto : examPortraitDto.getAbnormalRiskWarningDto().getQuesTionIntervalDtos()) {
                    quesTionIntervalDto.setQuestionName(questionIdOfName.get(quesTionIntervalDto.getQuestionId()));
                }
            }
            // 补充题目名称
            if (null != examPortraitDto.getAbnormalRiskWarningDto() && !CollectionUtils.isEmpty(examPortraitDto.getAbnormalRiskWarningDto().getRepetitionRateDtoList())){
                for (RepetitionRateDto repetitionRateDto : examPortraitDto.getAbnormalRiskWarningDto().getRepetitionRateDtoList()) {
                    repetitionRateDto.setQuestionName(questionIdOfName.get(repetitionRateDto.getQuestionId()));
                }
            }
            // 补充题目名称
            for (CodeSummarizeDto codeSummarizeDto : examPortraitDto.getCodeSummarizeDtos()) {
                codeSummarizeDto.setQuestionName(questionIdOfName.get(codeSummarizeDto.getQuestionId()));
            }
        }

        QueryWrapper<ExamPortrait> queryWrapper = new QueryWrapper<ExamPortrait>();
        ExamPortrait examPortrait = new ExamPortrait();
        // 生成完毕之后，先删除然后插入
        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
            queryWrapper.clear();
            queryWrapper.eq("exam_id", examPortraitDto.getExamId());
            queryWrapper.eq("user_id", examPortraitDto.getUserId());
            List<ExamPortrait> examPortraits = examPortraitService.getBaseMapper().selectList(queryWrapper);

            if (!CollectionUtils.isEmpty(examPortraits)){
                examPortraitService.getBaseMapper().deleteById(examPortraits.get(0).getId());
            }

            examPortraitDtoToExamPortrait(examPortraitDto,examPortrait);
            examPortraitService.getBaseMapper().insert(examPortrait);
        }
        LOGGER.info(examPortraitDtos.get(0).getExamId()+":用户画像生成结束");
    }

    // 更新用户画像数据
    private void examPortraitDtoToExamPortrait(ExamPortraitDto examPortraitDto,ExamPortrait examPortrait){
        examPortrait.setcId(examPortraitDto.getCId());
        examPortrait.setComprehensiveEvaluation(JsonUtils.serialize(examPortraitDto.getComprehensiveEvaluationDto()));
        examPortrait.setExamId(examPortraitDto.getExamId());
        examPortrait.setInfoStr(JsonUtils.serialize(examPortraitDto));
        examPortrait.setUserId(examPortraitDto.getUserId());
        examPortrait.setUserName(examPortraitDto.getUsername());
    }

    private void fiLlCodeSummarizeDtos(List<ExamPortraitDto> examPortraitDtos) {
        if (CollectionUtils.isEmpty(examPortraitDtos)){
            return;
        }
        // map<问题id，各用户得分>
        Map<Long, List<BigDecimal>> map = new HashMap<>();
        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
            List<CodeSummarizeDto> codeSummarizeDtos = examPortraitDto.getCodeSummarizeDtos();
            for (CodeSummarizeDto codeSummarizeDto : codeSummarizeDtos) {
                List<BigDecimal> orDefault = map.getOrDefault(codeSummarizeDto.getQuestionId(), new ArrayList<>());
                orDefault.add(codeSummarizeDto.getScore());
                map.put(codeSummarizeDto.getQuestionId(), orDefault);
            }
        }

        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
            List<CodeSummarizeDto> codeSummarizeDtos = examPortraitDto.getCodeSummarizeDtos();
            for (CodeSummarizeDto codeSummarizeDto : codeSummarizeDtos) {
                List<BigDecimal> orDefault = map.getOrDefault(codeSummarizeDto.getQuestionId(), new ArrayList<>());
                List<BigDecimal> collect = orDefault.stream().distinct().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
                codeSummarizeDto.setScoreOrder(collect.indexOf(codeSummarizeDto.getScore()) + 1);
            }
        }

    }

    // 历史数据处理
    public void durationScoreRecordDtoHandler(ExamPortraitDto examPortraitDto){
        // 设置查询条件
        QueryWrapper<ExamPortrait> queryWrapper = new QueryWrapper<ExamPortrait>();
        queryWrapper.eq("c_id", examPortraitDto.getCId());
        queryWrapper.eq("user_id", examPortraitDto.getUserId());
        queryWrapper.orderByAsc("create_time");  // 升序

        List<ExamPortrait> examPortraits = examPortraitService.getBaseMapper().selectList(queryWrapper);

        for (int i = 0; i < examPortraits.size(); i++) {
            if (StringUtils.isEmpty(examPortraits.get(i).getComprehensiveEvaluation())){
                DurationScoreRecordDto durationScoreRecordDto = new DurationScoreRecordDto();
                // 反序列化，解析
                ComprehensiveEvaluationDto deserialize = JsonUtils.deserialize(examPortraits.get(i).getComprehensiveEvaluation(), ComprehensiveEvaluationDto.class);
                durationScoreRecordDto.setExamOrder(i); // 考试顺序
                durationScoreRecordDto.setScore(deserialize.getScore());  //得分
                durationScoreRecordDto.setSort(deserialize.getSort());
                try {
                    examPortraitDto.getDurationScoreRecordDtos().add(durationScoreRecordDto);// 排名
                }catch (Exception e) {
                    LOGGER.info(String.valueOf(e));
                }
            }
        }
    }



    // 处理综合评价,排名
    public void comprehensiveEvaluationDtoHandler(ComprehensiveEvaluationDto comprehensiveEvaluationDto, List<BigDecimal> sumScoreList){
        comprehensiveEvaluationDto.setSort(sumScoreList.indexOf(comprehensiveEvaluationDto.getScore())+1);
    }

    // 处理技能图谱,生成 score（ActualSumScore / SumScore）、排名
    public void skillMapDtoHandler(Map<String,List<BigDecimal>> tagMapList , List<SkillMapDto> skillMapDtoList){
        for (SkillMapDto skillMapDto : skillMapDtoList) {
            // Score 为ActualSumScore / SumScore

            skillMapDto.setScore(skillMapDto.getActualSumScore().divide(skillMapDto.getSumScore(), 2, BigDecimal.ROUND_HALF_UP));
            //实际得分不为空
            if (!CollectionUtils.isEmpty(tagMapList.get(skillMapDto.getTagName()))){
                // 赋予排名
                skillMapDto.setScoreOrder(tagMapList.get(skillMapDto.getTagName()).indexOf(skillMapDto.getActualSumScore())+1);
            }
        }
    }

    // 填充codeCapacities的非元数据属性
    private double fillCodeCapacities(List<ExamPortraitDto> examPortraitDtos) {
        if (CollectionUtils.isEmpty(examPortraitDtos)){
            return 0;
        }
        //构建容器   minRunTimeContainer《问题id，运行时间》  每一个问题的最小有效运行时间(用于计算代码速度）
        Map<Long, Long> minRunTimeContainer = getMinRunTimeContainer(examPortraitDtos);
        System.out.println("minRunTimeContainer: "+ minRunTimeContainer);

        // 本次考试中，所有考生最快的作答时间（这个最快只考虑做对一半以上的编程题数）
        double maxEfficientTime = 0;
        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {   // 每个用户
            List<CodeCapacity> codeCapacities = examPortraitDto.getCodeCapacities();
            Integer efficientCount = 0;
            for (CodeCapacity codeCapacity : codeCapacities) {   // 每个题
                Long questionId = codeCapacity.getQuestionId();
                BigDecimal score = codeCapacity.getScore();
                BigDecimal questionSore = codeCapacity.getQuestionSore();
                Long runTime = codeCapacity.getRunTime();
                Long minRunTime = minRunTimeContainer.getOrDefault(questionId, 0L);
                codeCapacity.setScoreRate(score.divide(questionSore,2,BigDecimal.ROUND_HALF_UP));

                if (calculateCodeEfficiencyThanHalf(score,questionSore)){  // 得分超过该题总分的一半，才有代码效率
                    codeCapacity.setCodeEfficiency(new BigDecimal(minRunTime / runTime));
                    efficientCount++;
                }else {
                    codeCapacity.setCodeEfficiency(new BigDecimal(0));
                }
                codeCapacity.setThinking((codeCapacity.getScoreRate().divide(new BigDecimal(2),2, RoundingMode.HALF_UP))
                        .add((codeCapacity.getCodeEfficiency().divide(new BigDecimal(2),2, RoundingMode.HALF_UP))));
            }
            List<ExamUserScore> examUserScores = examUserScoreMapper.selectList(new LambdaQueryWrapper<ExamUserScore>()
                    .eq(ExamUserScore::getExamId, examPortraitDto.getExamId())
                    .eq(ExamUserScore::getUserId, examPortraitDto.getUserId()));
            // 获取考试时长 分钟
            double examTime = (double) ((examUserScores.get(0).getSubmitTime().getTime() - examUserScores.get(0).getEnterTime().getTime()) / 1000);
            System.out.println(examPortraitDto.getUserId() + "examTime: " + examTime);
            // 获取effcientTime ：有效题数efficientCount  / 考试时长
            double effcientTime = efficientCount / examTime;
            // 更新maxEfficientTime
            if (maxEfficientTime < effcientTime) {
                maxEfficientTime = effcientTime;
            }
            examPortraitDto.setEfficientTime(effcientTime);
        }
        return maxEfficientTime;
    }

    // 获取个题目 所有用户中所有提交记录运行得分大于一半的 最小运行时间，
    //
    private Map<Long, Long> getMinRunTimeContainer(List<ExamPortraitDto> examPortraitDtos) {
        // minRuntimeMap<问题id，运行时间>
        Map<Long, Long> minRuntimeMap = new HashMap<>();
        boolean isFirst = true;
        // 初始化minRuntimeMap，得分超过题目总分的一半，则存 时间，否则 存0代表为无效值
        for (CodeCapacity codeCapacity : examPortraitDtos.get(0).getCodeCapacities()) {
            if (codeCapacity.getScore().compareTo(codeCapacity.getQuestionSore().divide(BigDecimal.valueOf(2))) > 0) {
                minRuntimeMap.put(codeCapacity.getQuestionId(), codeCapacity.getRunTime());
            }else {
                minRuntimeMap.put(codeCapacity.getQuestionId(), 0L);  //为0作废
            }
        }
        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
            if (isFirst) {isFirst = false; continue;}
            for (CodeCapacity codeCapacity : examPortraitDto.getCodeCapacities()) {
                if (codeCapacity.getScore().compareTo(codeCapacity.getQuestionSore().divide(BigDecimal.valueOf(2))) > 0){
                    if (!minRuntimeMap.get(codeCapacity.getQuestionId()).equals(0L) && (codeCapacity.getRunTime().compareTo(minRuntimeMap.get(codeCapacity.getQuestionId())) > 0)){
                        continue;
                    }
                    minRuntimeMap.replace(codeCapacity.getQuestionId(), codeCapacity.getRunTime());
                }
            }
        }
//        for (ExamPortraitDto examPortraitDto : examPortraitDtos) {
//            long minRuntime = Long.MAX_VALUE; // 初始化为最大值
//            long minRuntimeId = -1L; // 初始化为无效值
//            for (CodeCapacity codeCapacity : examPortraitDto.getCodeCapacities()) {
//                // 仅当score分数超过题目的一半时才进行统计
//                if (codeCapacity.getScore().compareTo(codeCapacity.getQuestionSore().divide(BigDecimal.valueOf(2))) > 0) {
//                    if (codeCapacity.getRunTime() < minRuntime) {
//                        minRuntime = codeCapacity.getRunTime();
//                        minRuntimeId = codeCapacity.getQuestionId();
//                    }
//                }
//            }
//            if (minRuntimeId != -1L) { // 只有当有符合条件的实体时才将其放入统计中
//                minRuntimeMap.put(minRuntimeId, minRuntime);
//            }
//        }
        return minRuntimeMap;

    }

    // 是否超过一半
    private boolean calculateCodeEfficiencyThanHalf(BigDecimal score, BigDecimal totalScore) {
        BigDecimal halfTotalScore = totalScore.divide(new BigDecimal(2), 2, RoundingMode.HALF_UP);
        return score.compareTo(halfTotalScore) >= 0;
    }



}
